Scala の深い indent を Try 型の for 式に書き換へる pattern
そもそも深い indent は for 式に書き換へる機會
code:scala
f(x) match {
None => "none"
Some(y) => g(y) match {
None => "none"
Some(z) => h(z)
}
}
code:scala
(for {
y <- f(x)
z <- g(y)
} yield h(z)).getOrElse("none")
match する型が等しく、大域脱出する分枝の結果が等しいならば、for 式に書き換へられる
上記の例では、match する型は全て Option 型で、大域脱出する分枝の結果は全て "none"
ECMAScriptECMAScript.icon で callback 地獄を Promise object の method chain に置き換へたのに似る match する型が異なるならば、Try 型に變換するといい
code:scala
f(x) match {
None => "none"
Some(y) => g(y) match {
Left(_) => "none"
Right(z) => h(z)
}
}
code:scala
(for {
y <- f(x).toRight(new Exception()).toTry
z <- g(y).left.map(_ => ne Exception()).toTry
} yield h(z)).fold({ _ => "none" }, identity)
この例は人工的なので、この例だと Option[A] 型に變換するのが最良だけどね
大域脱出する分枝の結果が異なるならば、大域脱出した先で Throwable の型で條件分岐すればいい
code:scala
f(x) match {
None => "none1"
Some(y) => g(y) match {
None => "none2"
Some(z) => h(z)
}
}
code:scala
case class None1Exception() extends Exception("", None.orNull)
case class None2Exception() extends Exception("", None.orNull)
(for {
y <- f(x).toRight(new None1Exception()).toTry
z <- g(y).toRight(new None2Exception()).toTry
} yield h(z)).fold(
{
case _: None1Exception => "none1"
case _: None2Exception => "none2"
},
identity
)
この例は人工的なので、この例だと Either[String, B] 型に變換するのが最良だけどね